package com.baidu.iit.pxp.el;

import com.baidu.iit.pvm.delegate.VariableScope;
import com.baidu.iit.pxp.data.ItemInstance;
import com.baidu.iit.pxp.delegate.Expression;
import com.baidu.iit.pxp.el.juel.JuelExpression;
import com.baidu.iit.pxp.el.resolver.*;
import com.baidu.iit.pxp.entity.VariableScopeImpl;

import java.util.Map;

/**
 * 动态语言管理类
 * User: huangweili
 * Date: 14-4-25
 * Time: 上午10:11
 */
public class ExpressionManager {

    protected ExpressionFactory expressionFactory;


    protected ELContext parsingElContext = new ParsingElContext();
    protected Map<Object, Object> beans;


    public ExpressionManager() {
        this(null);
    }


    public ExpressionManager(Map<Object, Object> beans) {
        expressionFactory = new ExpressionFactoryImpl();
        this.beans = beans;
    }



    public Expression createExpression(String expression) {
        ValueExpression valueExpression = expressionFactory.createValueExpression(parsingElContext, expression.trim(), Object.class);
        return new JuelExpression(valueExpression, expression);
    }

    public void setExpressionFactory(ExpressionFactory expressionFactory) {
        this.expressionFactory = expressionFactory;
    }

    public ELContext getElContext(VariableScope variableScope) {
        ELContext elContext = null;
        if (variableScope instanceof VariableScopeImpl) {
            VariableScopeImpl variableScopeImpl = (VariableScopeImpl) variableScope;
            elContext = variableScopeImpl.getCachedElContext();
        }

        if (elContext==null) {
            elContext = createElContext(variableScope);
            if (variableScope instanceof VariableScopeImpl) {
                ((VariableScopeImpl)variableScope).setCachedElContext(elContext);
            }
        }

        return elContext;
    }

    protected ActivitiElContext createElContext(VariableScope variableScope) {
        ELResolver elResolver = createElResolver(variableScope);
        return new ActivitiElContext(elResolver);
    }

    protected ELResolver createElResolver(VariableScope variableScope) {
        CompositeELResolver elResolver = new CompositeELResolver();
        elResolver.add(new VariableScopeElResolver(variableScope));

        if(beans != null) {
            elResolver.add(new ReadOnlyMapELResolver(beans));
        }

        elResolver.add(new ArrayELResolver());
        elResolver.add(new ListELResolver());
        elResolver.add(new MapELResolver());
        elResolver.add(new DynamicBeanPropertyELResolver(ItemInstance.class, "getFieldValue", "setFieldValue"));
        elResolver.add(new BeanELResolver());
        return elResolver;
    }
}
